﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Thanhlichtek.BOS.Bullhorn.BullhornApi;

namespace Thanhlichtek.BOS.Bullhorn
{
    public class BullhornService
    {
        private static String _userName;
        private static String _password;
        private static String _apiKey;
        private static String _currentSession;
        private static DateTime _currentSessionDateTime;
        private static int _corporateId;
        private static int _userId;
        private static Dictionary<int, corporateUserDto> _corporateUserDict = new Dictionary<int, corporateUserDto>();
        private static Dictionary<int, clientCorporationDto> _clientCorporationDict = new Dictionary<int, clientCorporationDto>();

        private BullhornApi.ApiServiceClient _service;

        public String UserName 
        { 
            get {return _userName;} 
            set {_userName = value;}
        }

        //public corporateUserDto GetCorporateUser(int id)
        //{
        //    corporateUserDto result;
        //    if (_corporateUserDict.TryGetValue(id, out result))
        //    {
        //        return result;
        //    }
        //    else
        //    {
        //        return null;
        //    }
        //}

        private static void RefreshSession(BullhornApi.ApiServiceClient service)
        {
            lock (_currentSession)
            {
                var currentTime = DateTime.Now;
                var seconds = currentTime.Subtract(_currentSessionDateTime).TotalSeconds;
                if (seconds > 4 * 60)
                {
                    BullhornApi.apiStartSessionResult result = service.startSession(_userName, _password, _apiKey);
                    _currentSession = result.session;
                    _currentSessionDateTime = DateTime.Now;

                }

            }
        }

        public BullhornService(String userName, String password, String apiKey, bool createNewSession)
        {
            this.UserName = userName;
            _password = password;
            _apiKey = apiKey;

            _service = new BullhornApi.ApiServiceClient();

            if (createNewSession)
            {
                try
                {
                    BullhornApi.apiStartSessionResult result = _service.startSession(_userName, _password, _apiKey);
                    _currentSession = result.session;
                    _corporateId = result.corporationId;
                    _userId = result.userId;
                    _currentSessionDateTime = DateTime.Now;
                }
                catch (Exception)
                {
                    throw new UnauthorizedAccessException("Please check your Bullhorn user name and password.");
                }
            }
        }

        public object[] GetListIds()
        {
            dtoQuery myQuery = new dtoQuery();
            myQuery.entityName = "DistributionList";
            myQuery.maxResults = 50;

            // This query will find IDs of candidates with a status of 'New Lead" that were added after December 12, 2009
            // and are owned by CorporateUsers with an ID of 1, 2, 3, or 5.
            //myQuery.where = "owner.id = '" + _corporateId.ToString() + "'";

            myQuery.orderBys = new String[] { "dateAdded desc", "id asc" };
            RefreshSession(this._service);
            apiQueryResult qResult = _service.query(_currentSession, myQuery);

            object[] ids = qResult.ids;

            return ids;
        }

        public object[] SearchClientContactByEmail(string clientContactEmail)
        {
            dtoQuery myQuery = new dtoQuery();
            myQuery.entityName = "ClientContact";
            myQuery.where = "email = '" + clientContactEmail + "'";
            myQuery.maxResults = 50;

            // This query will find IDs of candidates with a status of 'New Lead" that were added after December 12, 2009
            // and are owned by CorporateUsers with an ID of 1, 2, 3, or 5.
            //myQuery.where = "owner.id = '" + _corporateId.ToString() + "'";

            myQuery.orderBys = new String[] { "dateAdded desc", "id asc" };
            RefreshSession(this._service);
            apiQueryResult qResult = _service.query(_currentSession, myQuery);

            object[] ids = qResult.ids;

            return ids;
        }

        public distributionListDto GetListInfo(object id)
        {

            int distributionListId = Int32.Parse(id.ToString());
            RefreshSession(this._service);
            apiFindResult distributionListResult = _service.find(_currentSession, "DistributionList", distributionListId);
            //currentSession = clientContactResult.session;
            distributionListDto thisDistributionList = (distributionListDto)distributionListResult.dto;

            ////Get Sales person
            //int ownerId = thisDistributionList.ownerID;
            //if (!_corporateUserDict.ContainsKey(ownerId))
            //{
            //    RefreshSession(this._service);
            //    apiFindResult corporateUserResult = _service.find(_currentSession, "CorporateUser", ownerId);
            //    corporateUserDto corporateUser = (corporateUserDto)corporateUserResult.dto;
            //    _corporateUserDict.Add(ownerId, corporateUser);
                
            //}

            return thisDistributionList;
        }


        public clientContactDto GetClientContact(object clientContactId)
        {
            int intClientContactId = Int32.Parse(clientContactId.ToString());
            RefreshSession(this._service);
            apiFindResult clientContactResult = _service.find(_currentSession, "ClientContact", intClientContactId);
            //currentSession = clientContactResult.session;
            clientContactDto thisClientContact = (clientContactDto)clientContactResult.dto;
            return thisClientContact;
        }

        //Company of a contact
        public clientCorporationDto GetClientCorporation(int clientCorporationId)
        {
            clientCorporationDto result;
            if (_clientCorporationDict.TryGetValue(clientCorporationId, out result))
            {
                return result;
            }
            else
            {
                lock (_clientCorporationDict)
                {
                    if (_clientCorporationDict.TryGetValue(clientCorporationId, out result))
                    {
                        return result;
                    }
                    else
                    {

                        RefreshSession(this._service);
                        apiFindResult clientCorporationResult = _service.find(_currentSession, "ClientCorporation", clientCorporationId);
                        clientCorporationDto clientCorporation = (clientCorporationDto)clientCorporationResult.dto;
                        _clientCorporationDict.Add(clientCorporationId, clientCorporation);

                        return clientCorporation;
                    }

                }
            }
        }

        //Owner of a contact
        public corporateUserDto GetCorporateUser(int corporateUserId)
        {
            corporateUserDto result;
            if (_corporateUserDict.TryGetValue(corporateUserId, out result))
            {
                return result;
            }
            else
            {
                lock (_corporateUserDict)
                {
                    if (_corporateUserDict.TryGetValue(corporateUserId, out result))
                    {
                        return result;
                    }
                    else
                    {

                        RefreshSession(this._service);
                        apiFindResult corporateUserDtoResult = _service.find(_currentSession, "CorporateUser", corporateUserId);
                        corporateUserDto corporateUser = (corporateUserDto)corporateUserDtoResult.dto;
                        _corporateUserDict.Add(corporateUserId, corporateUser);

                        return corporateUser;
                    }

                }
            }
        }

        public object[] GetClientContactIds(distributionListDto list)
        {
            RefreshSession(this._service);
            apiGetAssociationIdsResult result = _service.getAssociationIds(_currentSession, "DistributionList", list.distributionListID, "members");
            object[] ids = result.ids;
            return ids;
            
        }

        public clientContactDto SaveClientContact(clientContactDto clientContact)
        {
            RefreshSession(this._service);
            apiSaveResult result = _service.save(_currentSession, clientContact);
            return  (clientContactDto)result.dto;
        }
    }
}
